<?php

/**
 * @classname 接口公用控制器
 * @classaccess private
 * @decription 接口公用控制器
 * @author 张旭刚
 * @updateTime 2018年05月26日
 * @errorCode 100000|登录超时
 * @errorCode 100001|校验码错误
 */

namespace api\controllers;

use Yii;
use yii\web\Controller;
use api\models\Configure;
use api\models\Tokens;
use api\models\Customer;
use api\models\CustomerGroup;
use api\models\CustomerGroupDescription;
use api\models\Sms;
use api\models\Verify;
use api\models\Mails;
use PHPMailer\PHPMailer\PHPMailer;

class PublicController extends Controller {

    public $enableCsrfValidation;
    public $redis;
    public $customer;
    public $customerId;
    public $mobile;
    public $email;
    public $realname;
    public $customerGroup;
    public $token;
    public $headers;

    public function __construct($id, $module, $config = array()) {
        parent::__construct($id, $module, $config);
        $this->enableCsrfValidation = false;
        $this->headers = Yii::$app->request->headers;
        $this->redis = Yii::$app->redis;
        if (Yii::$app->session->isActive){Yii::$app->session->open();}
        $this->checkLogin();
    }

    /**
     * 检查登录状态
     */
    private function checkLogin() {
        $router = Yii::$app->request->get('r');
        $notLogins = explode(',', $this->config('notlogins'));
        if (!in_array($router, $notLogins)) {
            $headers = Yii::$app->request->headers;
            $token = $headers->get('token');
            $status = $this->checkToken($token);
            if (!$status) {
                $this->renderJson(['code' => 0, 'msg' => '登录超时', 'data' => ['result' => false], 'errorCode' => 100000]);
            }
        }
    }

    /**
     * 根据Token（登录令牌）获取当前用户信息
     */
    protected function checkToken($token) {
        if (empty($token)) {
            return false;
        }
        $data = $this->redisGet('token_' . $token);
        if (empty($data)) {
            $data = Tokens::find()->where(['token' => $token])->asArray()->one();
            $this->redisSet('token_' . $token, $data);
        }
        if (empty($data)) {
            return false;
        }
        $long = $this->config('token_timeout_long');
        if (time() - $data['ctime'] > $long) {
            return false;
        }
        $this->customer = $this->redisGet('user_' . $data['customer_id']);
        if (empty($this->customer)) {
            $this->customer = Customer::find()->select('customer_id,store_id,firstname AS realname,email,telephone AS mobile,fax,address_id,customer_group_id,ip,status,date_added')->where(['customer_id' => $data['customer_id'], 'status' => 1])->asArray()->one();
            $this->redisSet('user_' . $data['customer_id'], $this->customer);
        }
        $this->setCustomer();
        $this->token = $token;
        return true;
    }

    /**
     * 设置用户信息到类变量
     */
    protected function setCustomer() {
        $this->customerId = $this->customer['customer_id'];
        $this->mobile = $this->customer['mobile'];
        $this->email = $this->customer['email'];
        $this->realname = $this->customer['realname'];
        $this->customerGroup = $this->redisGet('user_group_' . $this->customer['customer_group_id']);
        if (empty($this->customerGroup)) {
            $this->customerGroup = CustomerGroup::find()->where(['customer_group_id' => $this->customer['customer_group_id']])->asArray()->one();
            $this->redisSet('user_group_' . $this->customer['customer_group_id'], $this->customerGroup);
        }
    }

    /**
     * 获取配置信息
     */
    protected function config($key) {
        //$data = $this->redisGet('configure_'.$key);
        //if(empty($data)){
        $model = new Configure();
        $data = $model->find()->select('val')->where('`key`=\'' . $key . '\'')->asArray()->one();
        //$this->redisSet('configure_'.$key, $data);
        //}
        return $data['val'];
    }

    /**
     * 从redis获取string数据
     */
    protected function redisGet($key) {
        return unserialize($this->redis->get($key));
    }

    /**
     * 向redis存储string数据
     */
    protected function redisSet($key, $value) {
        if (is_array($value) || is_object($value)) {
            $value = serialize($value);
        }
        return $this->redis->set($key, $value);
    }

    /**
     * 从redis获取hash数据
     */
    protected function redisHMSet($key, $data) {
        $status = true;
        foreach ((array) $data as $k => $v) {
            $status = $this->redis->hset($key, $k, $v);
        }
        return $status;
    }

    /**
     * 向redis的存储hash数据
     */
    protected function redisHGetAll($key) {
        $data = $this->redis->hgetall($key);
        $d = [];
        foreach ((array) $data as $k => $v) {
            if ($k % 2 == 0) {
                $d[$v] = $data[$k + 1];
            }
        }
        return $d;
    }

    /**
     * 产生重复的唯一编号
     */
    protected function getGuid($prefix = '') {
        if (function_exists('com_create_guid')) {
            $guid = com_create_guid();
        } else {
            $rnd = mt_srand((double) microtime() * 10000); //optional for php 4.2.0 and up.
            $charid = strtoupper(md5(uniqid(rand(), true)));
            $hyphen = chr(45); // "-"
            $guid = chr(123) . substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12) . chr(125); // "}"
        }
        $guid = str_replace('{', '', $guid);
        $guid = str_replace('}', '', $guid);
        return $guid;
    }

    /**
     * 产生验证码并保存
     */
    protected function getVerifyCode($target, $targetType) {
        $rnd = rand(100000, 999999);
        $data = Verify::find()->where(['target' => $target, 'targetType' => $targetType])->asArray()->one();
        $verify = empty($data) ? new Verify() : Verify::findOne($data['id']);
        $verify->target = $target;
        $verify->targetType = $targetType;
        $verify->verify_code = $rnd;
        $verify->create_at = time();
        if($verify->save(false)){return $rnd;}
        return false;
    }

    /**
     * 发送短信
     * fanhuizhen@cardpsbc.com;yangpeipei@cardpsbc.com
     */
    protected function sendSms($mobile, $content) {
        if (is_array($mobile)) {$mobile = implode(',', $mobile);}
        if (empty($mobile)) {return 'mobile_is_empty';}
        if (empty($content)) {return 'message_is_empty';}
        $api = $this->config('send_sms');
        $data['appId'] = 'trade';
        $data['appName'] = 'trade';
        $data['mobiles'] = $mobile;
        $data['message'] = $content;
        $data['level'] = 2;
        $data['templateId'] = 'SMS_0';
        $data['templateParams '] = '';
        $result = json_decode($this->postSms($api, $data));
        $model = new Sms();
        $model->mobile = $mobile;
        $model->message = (string) $content;
        $model->send_time = time();
        $model->send_times = 1;
        if ($result->errorCode == 0) {
            $model->send_status = 1;
            $model->save();
            return 'success';
        }
        $model->send_status = 2;
        $model->save();
        return 'fail';
    }

    protected function postSms($url, $data) {
        $port = $this->getPortFromUrl($url);
        $data = json_encode($data);
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_PORT => $port,
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS => $data,
            CURLOPT_HTTPHEADER => array(
                "cache-control: no-cache",
                "content-type: application/json",
                "postman-token: 07ebf710-db28-8851-c109-3e913dd08d5d"
            ),
        ));
        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        return $err ? json_encode(['errorCode' => 1]) : $response;
    }

    private function getPortFromUrl($url) {
        $urls = explode('/', $url);
        if (!empty($urls) && isset($urls[2])) {$urls = explode(':', $urls[2]);}
        return count($urls) > 1 ? $urls[1] : '80';
    }
    
    protected function checkImgVerify($imgVerify){
        $guid = $this->headers['guid'];;
        return $imgVerify == $this->redis->get('session_'.$guid.'_verifyCode');
    }
    
    /**
     * 判断sign是否正确,sign的正确姿势：以参数名的key为准对参数进行字母顺序排列，形如：a=1&b=4&c=2
     * @param type $data
     * @param type $sign
     * @return type
     */
    protected function checkSign($data){
        $sign = Yii::$app->request->post('sign');
        if(empty($sign)){return $this->renderJson(['code' => 0, 'msg' => '校验码错误', 'data' => ['result' => false], 'errorCode' => 100001]);}
        $s = $this->getSign($data);
        if($s != $sign){$this->renderJson(['code' => 0, 'msg' => '校验码错误', 'data' => ['result' => false], 'errorCode' => 100002]);}
    }


    /**
     * SIGN的获取方式
     * @param type $str
     */
    protected function getSign($data){
        $salt = $this->config('sha256_salt');
        return $this->sha256($data, $salt);
    }
    
    /**
     * SHA256加密
     * @param type $data
     * @param type $salt
     * @return type
     */
    protected function sha256($data, $salt) {
        return hash_hmac("sha256", $data, $salt);
    }
    
    /**
     * 
     * 发送邮件
     * @param type $to_emails
     * @param type $subject
     * @param type $html_body
     * @param type $cc_emails
     * @param type $alt_body
     * @param type $attach_files
     * @return string
     */
    protected function sendEmail($to_emails, $subject, $html_body, $cc_emails = [], $alt_body = '', $attach_files = []) {
        if (empty($to_emails)) {return 'to_emails_is_empty';}
        if (empty($subject)) {return 'subject_is_empty';}
        if (empty($subject)) {return 'body_is_empty';}
        $set = explode('|', $this->config('send_email_setting'));
        $mail = new PHPMailer();
        $mail->isSMTP();
        $mail->CharSet = 'UTF-8';
        $mail->Host = $set[0];
        $mail->Port = $set[1];
        $mail->SMTPAuth = true;
        $mail->Username = $set[2];
        $mail->Password = $set[3];
        $mail->setFrom($set[4], $set[5]);
        foreach ((array) $to_emails as $k => $to_email) {$mail->addAddress($to_email);}
        foreach ((array) $cc_emails as $k => $cc_email) {$mail->addCC($cc_email);}
        $mail->Subject = $subject;
        $mail->msgHTML($html_body);
        $mail->AltBody = $alt_body;
        foreach ((array) $attach_files as $k => $file) {
            $mail->addAttachment($file);
        }
        $result = $mail->send();
        $send_status = $result ? 1 : 2;
        $model = new Mails();
        $model->to_emails = implode('|', $to_emails);
        $model->cc_emails = implode('|', $cc_emails);
        $model->subject = $subject;
        $model->html_body = $html_body;
        $model->alt_body = $alt_body;
        $model->attach_files = implode('|', $attach_files);
        $model->send_time = time();
        $model->send_status = $send_status;
        $model->send_times = 1;
        $model->save();
        if ($result) {
            return "send_success";
        }
    }

}
